//
//  YLRechargeCacheModel.swift
//  Distance
//
//  Created by changhe on 2025/4/27.
//

import Foundation
import StoreKit

struct YLUnfinishedTransactionsCacheModel: Codable {
	var transactionIdentifier: String?
	var originalTransactionId: String?
	let orderId: String?
	let createDate: Date
	let productId: String
	
	init(transactionIdentifier: String?, originalTransactionId: String? = nil, orderId: String?, productId: String) {
		self.transactionIdentifier = transactionIdentifier
		self.originalTransactionId = originalTransactionId
		self.orderId = orderId
		self.productId = productId
		self.createDate = Date()
	}
}

struct YLUnfinishedTransactionsCache {
	
	// MARK: - 常量
	
	static let key = "com.paymentKit.unfinishedTransactionsCache"
	
	private static let cacheFileURL: URL = {
		let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
		return documentsDirectory.appendingPathComponent("YLUnfinishedTransactions.json")
	}()
	
	private static let cacheQueue = DispatchQueue(label: "com.paymentKit.cacheQueue", attributes: .concurrent)
	
	// MARK: - 缓存数据
	
	private static var cacheModels: [YLUnfinishedTransactionsCacheModel] = {
		return loadFromDisk()
	}()
	
	// MARK: - 查找方法
	
	static func findModel(transaction: SKPaymentTransaction) -> YLUnfinishedTransactionsCacheModel? {
		guard let transactionIdentifier = transaction.transactionIdentifier else { return nil }
		return findModel(transactionId: transactionIdentifier)
	}
	
	static func findOwnOrderId(for transaction: SKPaymentTransaction) -> String? {
		return findModel(transaction: transaction)?.orderId
	}
	
	static func findModel(transactionId: String) -> YLUnfinishedTransactionsCacheModel? {
		var result: YLUnfinishedTransactionsCacheModel?
		cacheQueue.sync {
			result = cacheModels.first { $0.transactionIdentifier == transactionId }
		}
		return result
	}
	
	// MARK: - 缓存管理
	
	static func saveOnDisk() {
		cacheQueue.async(flags: .barrier) {
			do {
				let encoder = JSONEncoder()
				let data = try encoder.encode(cacheModels)
				try data.write(to: cacheFileURL, options: .atomicWrite)
				debugPrint("[YLPaymentKit] 成功保存未完成交易缓存，数量: \(cacheModels.count)")
			} catch {
				debugPrint("[YLPaymentKit] 保存未完成交易缓存失败: \(error.localizedDescription)")
			}
		}
	}
	
	private static func loadFromDisk() -> [YLUnfinishedTransactionsCacheModel] {
		do {
			guard FileManager.default.fileExists(atPath: cacheFileURL.path) else {
				return []
			}
			
			let data = try Data(contentsOf: cacheFileURL)
			let decoder = JSONDecoder()
			let loadedCache = try decoder.decode([YLUnfinishedTransactionsCacheModel].self, from: data)
			debugPrint("[YLPaymentKit] 成功加载未完成交易缓存，数量: \(loadedCache.count)")
			return loadedCache
		} catch {
			debugPrint("[YLPaymentKit] 加载未完成交易缓存失败: \(error.localizedDescription)")
			return []
		}
	}
	
	static func addRecord(record: YLUnfinishedTransactionsCacheModel) {
		guard let transactionIdentifier = record.transactionIdentifier else { return }
		
		cacheQueue.async(flags: .barrier) {
			if let index = cacheModels.firstIndex(where: { $0.transactionIdentifier == transactionIdentifier }) {
				cacheModels[index] = record
			} else {
				cacheModels.append(record)
			}
			saveOnDisk()
		}
	}
	
	static func addRecord(transaction: SKPaymentTransaction) {
		guard let transactionIdentifier = transaction.transactionIdentifier, let applicationUsername = transaction.payment.applicationUsername else { return }
		let ownOrderId = YLOrderUUIDTransformer.fromUUID(applicationUsername)
		let record = YLUnfinishedTransactionsCacheModel(
			transactionIdentifier: transactionIdentifier,
			originalTransactionId: transaction.original?.transactionIdentifier,
			orderId: ownOrderId,
			productId: transaction.payment.productIdentifier
		)
		addRecord(record: record)
	}
	
	static func removeRecord(transaction: SKPaymentTransaction) {
		guard let transactionIdentifier = transaction.transactionIdentifier else { return }
		removeRecord(transactionId: transactionIdentifier)
	}
	
	static func removeRecord(transactionId: String) {
		cacheQueue.async(flags: .barrier) {
			cacheModels.removeAll { $0.transactionIdentifier == transactionId }
			saveOnDisk()
		}
	}
	
	static func getAllRecords() -> [YLUnfinishedTransactionsCacheModel] {
		var result: [YLUnfinishedTransactionsCacheModel] = []
		cacheQueue.sync {
			result = cacheModels
		}
		return result
	}
}
